﻿using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace Common
{
    public class Result
    {
        public bool Succ { get; set; }
        public string Message { get; set; }
    }

    /// <summary>
    /// 模拟PLC读写类
    /// </summary>
    public class PLCMNHelper
    {
        Socket _socket;
        string _ipAddress;
        int _port;
        byte[] _receiveBytes = new byte[5024];
        int? _receiveLen;

        public PLCMNHelper(string ipAddress, int port)
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _ipAddress = ipAddress;
            _port = port;
        }

        public Result Connect()
        {
            Result result = new Result();
            IPAddress ip = IPAddress.Parse(_ipAddress);
            IPEndPoint iPEndPoint = new IPEndPoint(ip, _port);
            EndPoint remote = (EndPoint)(iPEndPoint);
            try
            {
                _socket.Connect(iPEndPoint);
                if (_socket.Connected)
                {
                    result.Succ = true;
                    Task.Factory.StartNew(() => {
                        while (true)
                        {
                            try
                            {
                                if (_socket.Connected)
                                {
                                    return;
                                }

                                _receiveLen = _socket.Receive(_receiveBytes);
                                if (_socket.Connected)
                                {
                                    return;
                                }
                            }
                            catch (SocketException ex)
                            {
                                _socket.Close();
                                return;
                            }
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.ToString() + ex.StackTrace;
            }

            return result;
        }

        public Result Read(string address)
        {
            Result result = new Result();
            string plcmsg = "plc_read#" + address;
            result = Send(plcmsg);
            return result;
        }

        public Result Write(string address, string val)
        {
            Result result = new Result();
            string plcmsg = "plc_write#" + address + "#" + val;
            result = Send(plcmsg);
            return result;
        }

        public Result Write(string address, byte[] buffer)
        {
            Result result = new Result();
            string plcmsg = "plc_batch_write#" + address + "#" + BitConverter.ToString(buffer);
            result = Send(plcmsg);
            return result;
        }

        public Result Send(string msg)
        {
            Result result = new Result();

            try
            {
                byte[] buffer = Encoding.UTF8.GetBytes(msg);
                _socket.Send(buffer);
                Thread.Sleep(100);
                string rspmsg = Encoding.UTF8.GetString(_receiveBytes, 0, _receiveLen.Value);
                string[] rspmsg_arr = rspmsg.Split('#');
                result.Succ = rspmsg_arr[0].Equals("OK") ? true : false;
                result.Message = rspmsg_arr[rspmsg_arr.Length - 1];
            }
            catch (Exception ex)
            {
                result.Message = ex.ToString() + ex.StackTrace;
            }

            return result;
        }

        public Result Close()
        {
            Result result = new Result();

            try
            {
                _socket.Close();
                _socket.Dispose();
                result.Succ = true;
            }
            catch (Exception ex)
            {
                result.Message = ex.ToString() + ex.StackTrace;
            }

            return result;
        }
    }
}
